// This file is a part of Funky C++.
// Copyright (C) 2011  Valentin David
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
#ifndef STRETCH_HH
# define STRETCH_HH

namespace funky {

  template <typename Signal>
  struct signal_stretch {
  private:
    typedef typename signal_traits<Signal>::sample sample;
    typedef typename signal_traits<Signal>::duration duration;
    Signal signal;
    duration ratio;

  public:
    template <typename T>
    signal_stretch(T&& s, const duration& ratio):
      signal(std::forward<T>(s), ratio),
      ratio(ratio)
    {}
    signal_stretch(const signal_stretch&) = default;
    signal_stretch(signal_stretch&&):
      signal(std::move(signal)),
      ratio(std::move(ratio)) {
    }

    signal_stretch& operator=(const signal_stretch& other) {
      return *this = signal_stretch(other);
    }

    signal_stretch& operator=(signal_stretch&& other) {
      std::swap(signal, other.signal);
      std::swap(ratio, other.ratio);
      return *this;
    }

    signal_stretch& operator+=(const duration& d) {
      signal += d;
      return *this;
    }
  };

  template <typename Signal>
  struct signal_traits<signal_stretch<Signal> > {
    typedef typename signal_traits<Signal>::duration duration;
    typedef typename signal_traits<Signal>::sample sample;
  };

  template <typename T, typename RT = typename std::decay<T>::type,
	    typename Duration = typename signal_traits<RT>::duration>
  signal_traits<signal_stretch<RT> >
  stretch(T&& t, typename std::identity<Duration>::type ratio) {
    return signal_traits<signal_stretch<RT> >{
      std::forward<T>(t), ratio
	};
  }

}

#endif
